<?php

namespace MediatorPattern;

/**
 * 中介者模式的角色和职责
 * 1. 抽象中介者(Mediator)：定义了所有中介者实例都需要实现的方法
 * 2. 具体中介者(ConcreteMediator)，实现中介者接口，协调各个具体同事对象之间的通信。
 * 3. 抽象同事类(Colleague)：每个同事对象都持有中介者对象的引用，并通过它与其他同事通信。
 * 4. 具体同事类(ConcreteColleague)：实现具体的同事逻辑，需要与其他对象通信时，通过中介者转发。
 */

// 以聊天室为例，实现中介者模式

// 1. 定义抽象中介者接口，规定了发送消息和用户注册
interface ChatRoomMediator
{
    public function sendMessage(User $user, string $message): void;
    public function register(User $user): void;
}

// 2. 定义抽象同事类，规定发送消息到中介者和接收消息
abstract class User
{
    protected string $name;
    protected ChatRoomMediator $chatRoomMediator;

    /**
     * @param string $name
     * @param ChatRoomMediator $chatRoomMediator
     */
    public function __construct(string $name, ChatRoomMediator $chatRoomMediator)
    {
        $this->name = $name;
        $this->chatRoomMediator = $chatRoomMediator;
    }

    public function send(string $message)
    {

    }

    public function receive(string $message)
    {
        
    }
}

// 3. 实现同事类
class CharUser extends User
{
    public function send(string $message): void
    {
        echo "【{$this->chatRoomMediator->getName()}】 $this->name 发送消息： $message\n";
        $this->chatRoomMediator->sendMessage($this, $message);
    }

    public function receive(string $message): void
    {
        echo "【{$this->chatRoomMediator->getName()}】 {$this->name}：收到消息： ";
        echo "$message\n";
    }
}
// 3. 实现中介类
class ChatRoom implements ChatRoomMediator
{
    private string $name;
    private array $userList = [];

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }


    /**
     * @param string $name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function sendMessage(User $user, string $message): void
    {
        foreach ($this->userList as $item) {
            if ($item instanceof User && $item !== $user) {
                $item->receive($message);
            }
        }
    }

    public function register(User $user): void
    {
        $this->userList[] = $user;
    }

}
// 测试
$chatRoom = new ChatRoom("学习聊天室");
$user1 = new CharUser("小王", $chatRoom);
$chatRoom->register($user1);
$user2 = new CharUser("小李", $chatRoom);
$chatRoom->register($user2);
$user3 = new CharUser("小张", $chatRoom);
$chatRoom->register($user3);
$user1->send("大家好");

$chatRoom2 = new ChatRoom("游戏聊天室");
$user4 = new CharUser("小赵", $chatRoom2);
$chatRoom2->register($user4);
$user5 = new CharUser("小孙", $chatRoom2);
$chatRoom2->register($user5);
$user4->send("新游戏真不错");